#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "/usr/local/include/pbc/pbc.h"
#include "/usr/local/include/pbc/pbc_test.h"
#include <math.h>

#define NMAX 1000 //block number
//#define C 100//challlenge number
#define  CMAX  1000//challlenge number

	//生成文件

typedef struct 
{
	element_t m[NMAX], auth[NMAX];
}File;
File f;



typedef struct  
{
	int cj[NMAX];
	element_t cvj[NMAX];
}Challenge;
Challenge c;


double t1, t2;
int i, j;


int main(int argc, char **argv) {


FILE *fp;//文件指针

    fp=fopen("data.txt","w");//fopen打开文件，这个文件可以是当前不存在的。“w”以写入的形式打开，“r”以读的形式打开
    if(fp==NULL) //判断如果文件指针为空
    {
        printf("File cannot open! " );
        exit(0);//在以0的形式退出，必须在文件开头有#include <stdlib.h>,stdlib 头文件即standard library标准库头文件
    }



	//系统参数
	pairing_t pairing;
	pbc_demo_pairing_init(pairing, argc, argv);

  	element_t y, b, g;	
	element_init_Zr(y, pairing);
	element_random(y);	
	element_init_Zr(b, pairing);
	element_random(b);
	element_init_G1(g, pairing);
	element_random(g);
	
	int r0 = 20, z0 = 30, x0 = 40;
	element_t r, z, x;
	element_init_Zr(r, pairing);
	element_init_Zr(z, pairing);
	element_init_Zr(x, pairing);
	element_random(r);
	element_random(z);
	element_random(x);
	
	element_t dvy, pky, pkr, pkb;	
	element_init_Zr(dvy, pairing);
	element_div(dvy, y, z);
	element_init_G1(pky, pairing);
	element_pow_zn(pky, g, y);
	element_init_G1(pkr, pairing);
	element_t pkr0;
	element_init_Zr(pkr0, pairing);
	element_div(pkr0, y, r);
	element_pow_zn(pkr, g, pkr0);
	element_init_G1(pkb, pairing);
	element_pow_zn(pkb, g, y);
	element_pow_zn(pkb, pkb, b);
	
	for ( i = 0; i < NMAX; i++ )
	{
		element_init_Zr(f.m[i], pairing);
		element_random(f.m[i]);
	}
	element_t IDF, IDC;
	element_init_Zr(IDF, pairing);
	element_init_Zr(IDC, pairing);
	element_random(IDF);
	element_random(IDC);
	
	int n0=1;
	element_t n;
	element_init_Zr(n, pairing);
	element_set_si(n, n0);
//AuthGen
       
	element_t H[NMAX];
	element_t dj, ksi;
	element_init_Zr(dj, pairing);
	element_init_Zr(ksi, pairing);
	int dj0=50;	
	element_random(dj);
	element_random(ksi);
	//放在全局方便后续取用
	   
for(int N = 100; N<1001; N+=100)
{
//int N=1000;
    
	//fprintf(fp, "数据块数量 = %d\n", N);
	t1=pbc_get_time();	 
	
	//for each data block
	
	for ( j = 0; j < N; j++ )
	{		
		
		
		element_init_Zr(H[j], pairing);
		element_from_hash(H[j], (char *)"IDF || j || IDC", sizeof("IDF || j || IDC"));
		
		element_init_Zr(f.auth[j], pairing);
		element_add(f.auth[j], ksi, f.m[j]);
		element_add(f.auth[j], f.auth[j], dj);
		element_t bH;
		element_init_Zr(bH, pairing);
		element_mul(bH, b, H[j]);
		element_add(f.auth[j], f.auth[j], bH);
		element_t rxd;
		element_init_Zr(rxd, pairing);
		element_add(rxd, f.m[j], dj);
		element_mul(rxd, r, rxd);
		element_add(f.auth[j], f.auth[j], rxd);
	
	}
	t2=pbc_get_time();
	double time_fauth = t2-t1;
	
	
	//fprintf(fp, "认证器生成时间 = %f\n", time_fauth);
	
	
	t1=pbc_get_time();
	for(i=0;i<N;i++)
	{
	element_t a1;
	element_init_Zr(a1, pairing);
	element_div(a1, f.auth[i], dvy);
	element_mul(a1, a1, dvy);
	element_sub(a1, f.auth[i], a1);
	element_div(a1, a1, r);
	element_sub(a1, a1, x);}
	t2=pbc_get_time();
	double tt=t2-t1;
	//fprintf(fp, "%f\n", tt);
	

}


//fprintf(fp, "=============================================================\n");
//fprintf(fp, "质询阶段，数据块数量 = 1000 \n");
	   
	element_t au1[NMAX], AP1;
	//au2和miu2是最终版
	element_init_Zr(AP1,pairing);
	element_set0(AP1);

	
for(int C = 100; C<1001; C+=100)
{	
//int C=100;
	//fprintf(fp, "被质询的数据块数量 = %d\n", C);
//ChallengeGen

	t1 = pbc_get_time();
	
	
	
	for(j = 0; j < C; j++)
	{			
		c.cj[j] = rand() % NMAX;
		element_init_Zr(c.cvj[c.cj[j]], pairing);
		element_random(c.cvj[c.cj[j]]);
	}
	
	t2 = pbc_get_time();		
	//fprintf(fp, "质询生成时间 = %f\n", t2 - t1);	

//ProofGen
    t1 = pbc_get_time();

	for(j = 0; j < C; j++)
	{	
		element_init_Zr(au1[c.cj[j]], pairing);
		element_mul(au1[c.cj[j]], c.cvj[c.cj[j]], f.auth[c.cj[j]]);
		element_add(AP1, AP1, au1[c.cj[j]]);	
	}
	
	t2 = pbc_get_time();		
	//fprintf(fp, "%f\n", t2 - t1);	
	
//ProofVerify
    t1 = pbc_get_time();
     
    element_t Hc[NMAX], vjksi[NMAX], Add_vjksi;
	element_init_Zr(Add_vjksi, pairing);
	element_set0(Add_vjksi);
       
	for (j = 0; j < C; j++)
	{		
		element_init_Zr(Hc[c.cj[j]], pairing);
		element_from_hash(Hc[c.cj[j]], (char *)"IDF || c.cj[j] || IDC", sizeof("IDF || c.cj[j] || IDC"));

	}//得到H
	
	element_t Adv;
	element_init_Zr(Adv, pairing);
	
	element_div(Adv, AP1, dvy);
	

	
	element_t fAdv;
	element_init_Zr(fAdv, pairing);
	//element_set(fAdv, floor(Adv_floor));
	//element_set_si(fAdv, Adv_floor);
	element_mul(fAdv, fAdv, dvy);//得到floor
	
	element_t gfloor;
	element_init_G1(gfloor, pairing);
	element_pow_zn(gfloor, g, fAdv);//得到左边第一个值
	
	for(j=0;j<C;j++)
	{
		element_init_Zr(vjksi[c.cj[j]], pairing);
		element_mul(vjksi[c.cj[j]], c.cvj[c.cj[j]], ksi);
		element_add(Add_vjksi, Add_vjksi, vjksi[c.cj[j]]);
    }
	// 由于是单云，所以n等于1
	element_t n_Add_vjksi;
	element_init_Zr(n_Add_vjksi, pairing);
	element_mul(n_Add_vjksi, n, Add_vjksi);
	
	
	element_t pky_ver;
	element_init_G1(pky_ver, pairing);
	element_pow_zn(pky_ver, pky, n_Add_vjksi);//得到右边第一个值
	
	element_t AP1_floor;
	element_init_Zr(AP1_floor, pairing);
	element_sub(AP1_floor, AP1, fAdv);
	element_t pkr_AP1_floor;
	element_init_G1(pkr_AP1_floor, pairing);
	element_pow_zn(pkr_AP1_floor, pkr, AP1_floor);//得到右边第二个值
	
	element_t vjH[NMAX], Add_vjH;
	element_init_Zr(Add_vjH, pairing);
	element_set0(Add_vjH);
	
	for(j=0;j<C;j++)
	{
		element_init_Zr(vjH[c.cj[j]], pairing);
		element_mul(vjH[c.cj[j]], c.cvj[c.cj[j]], Hc[c.cj[j]]);
		element_add(Add_vjH, Add_vjH, vjH[c.cj[j]]);
    }
	
	element_t pkb_Add_vjH;
	element_init_G1(pkb_Add_vjH, pairing);
	element_pow_zn(pkb_Add_vjH, pkb, Add_vjH);//得到右边第三个值
	
	element_t right;
	element_init_G1(right, pairing);
	element_mul(right, pky_ver, pkr_AP1_floor);
	element_mul(right, right, pkb_Add_vjH);
	
	if(!element_cmp(gfloor, right) )
	{
		printf("success\n");
	}
	else{printf("fail\n");}
	
	
	
	t2 = pbc_get_time();
	
	fprintf(fp, "%f\n", t2 - t1);
	//fprintf(fp, "\n");
	
}
/*
*/

	
	 //关闭文件
    	fclose(fp);
	return 0;
}
	
	
	
